using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace HuaXianQu.ProtoBuffEx.ToolEditor
{
    /// <summary>
    /// 自定义类生成器
    /// </summary>
    public class CustomClassGen : IProtoType
    {
        ProtoBasicTypeParse _protoBasicTypeParse = new ProtoBasicTypeParse();
        private string proto;

        public string Parse(List<string> lines, string tableName = null)
        {
            List<VariableInfo> variables = new List<VariableInfo>();
            ClassName = lines[0].Trim();
            string fieldName = null;
            CurObjectInfo.CustomVariableNameList.Add(ClassName);
            for (int i = 1; i < lines.Count; i++)
            {
                string value = lines[i].Trim();
                string[] matches = value.Split(':');
                if (matches.Length != 3)
                {
                    continue;
                }

                VariableInfo.DataType dataType = VariableInfo.DataType.Basic;
                string protoType = matches[0].Trim();
                Match tempMatch;
                //非基础类
                if (!_protoBasicTypeParse.ParseType(protoType.ToLower(), out string type))
                {
                    tempMatch = Regex.Match(protoType, @"List[\s\t]*<[\s\t]*([\w]+)[\s\t]*>");
                    if (tempMatch.Groups.Count == 2)    //列表类
                    {
                        fieldName = tempMatch.Groups[1].Value;
                        type = $"repeated {fieldName}";
                        dataType = VariableInfo.DataType.List;
                        if (!_protoBasicTypeParse.ParseType(fieldName, out _))
                        {
                            dataType = VariableInfo.DataType.CustomList;
                        }
                    }
                    else    //词典类
                    {
                        tempMatch = Regex.Match(protoType, @"Dictionary[\s\t]*<[\s\t]*([\w]+)[\s\t]*,[\s\t]*([\w]+)[\s\t]*>");
                        if (tempMatch.Groups.Count == 3)
                        {
                            dataType = VariableInfo.DataType.Dictionary;
                            if (!_protoBasicTypeParse.ParseType(tempMatch.Groups[1].Value, out string dictType))
                            {
                                dictType = tempMatch.Groups[1].Value;
                            }

                            if (!_protoBasicTypeParse.ParseType(tempMatch.Groups[2].Value, out fieldName))
                            {
                                fieldName = tempMatch.Groups[2].Value;

                                if (!_protoBasicTypeParse.ParseType(fieldName.ToLower(), out _))
                                {
                                    dataType = VariableInfo.DataType.CustomDictionary;
                                }
                            }

                            type = $"map<{dictType},{fieldName}>";
                        }
                        else //自定义类或者枚举
                        {
                            dataType = VariableInfo.DataType.Custom;
                            fieldName = protoType;
                            type = protoType;
                        }
                    }
                }

                if (int.TryParse(matches[2], out int index))
                {
                    var variableInfo = new VariableInfo()
                    {
                        VariableType = type,
                        VariableName = matches[1],
                        CustomVariableName = fieldName,
                        ProtoIndex = index,
                        CurDataType = dataType,
                    };
                    variables.Add(variableInfo);
                    if (variableInfo.IsExistsCustomClass())
                    {
                        CurObjectInfo.ReferenceOfVariableNameList.Add(variableInfo.CustomVariableName);
                    }
                }
            }

            
            proto = $"message {ClassName}\n{{\n{string.Join('\n', variables)}\n}}";
            return proto;
        }


        public string ClassName { get; set; }
        public ObjectInfo CurObjectInfo { get; set; } = new ObjectInfo();
        public bool IsDataClass { get; set; }

        public override string ToString()
        {
            return proto;
        }
    }
}